package com.nf.db.handler;

import com.nf.db.ResultSetHandler;

import java.sql.ResultSet;
import java.sql.SQLException;

import static com.nf.db.RowProcessor.DEFAULT_ROWPROCESSOR;

/**
 * 此类默认是取第一条记录的指定列的值，这一列的类型是无法预知的
 * 所以此类设计为泛型类
 * <p>
 * 这个类有告诉大家怎么写构造函数，通常是这样的规则
 * 1.写一个参数最多的构造函数
 * 2.其它构造函数就调用上面的那一个
 * <p>
 * 构造函数一般不写复杂逻辑代码，就是一些简单的给字段赋值的代码
 * 如果真的出现了复杂逻辑代码，请写一个init的方法，然后构造函数调用这个方法
 *
 * @param <T>
 */
public class ScalarHandler<T> implements ResultSetHandler<T> {

    private String columnName;

    /**
     * 此种写法，有个潜在的问题
     * 就是两个参数不是指向同一列数据，那么怎么处理？
     * 要么就是报错，要么以哪一个数据为准的解决办法
     *
     * @param columnName
     */
    public ScalarHandler(String columnName) {
        //super()
        this.columnName = columnName;
        init();
    }

    private void init() {
    }


    /*@Override
    public T handle(ResultSet rs) throws SQLException {
        //因为只取第一条记录，所以这里是if，而不是经常写的while
        if (rs.next()) {
            //如果没有列名，就取列的索引对应列的记录数据
            // 这种写法表明当列索引与列名冲突，指向不是同一列时，优先以列名来取值
            if (this.columnName == null) {
                return (T) rs.getObject(this.columnIndex);
            }
            //这里可以写else，但没必要（return语句提前结束），
            //现在的代码写法更好，更简洁
            return (T) rs.getObject(this.columnName);
        }
        // 代码走到这里，就意味着没有记录
        return null;
    }*/

    @Override
    public T handle(ResultSet rs) throws SQLException {
        //提前结束方法执行的逻辑先写，避免过多的if嵌套
        return rs.next() ? DEFAULT_ROWPROCESSOR.toScalar(rs, this.columnName) : null;
    }
}
